/*
 * @Author: FanWeiHua
 * @Date: 2021-05-26 19:16:19
 * @LastEditTime: 2021-07-16 14:52:40
 * @Description: 工具类
 */
const fs = require('fs');
const os = require('os');
const path = require('path');
/**
 * 验证手机号
 */
exports.isPhoneNo = phoneNo => {
  const reg = /^1[3456789]\d{9}$/;
  return reg.test(phoneNo);
};
/**
 * 验证邮箱地址
 */
exports.isEmail = email => {
  const reg = /^[0-9a-zA-Z_.-]+[@][0-9a-zA-Z_.-]+([.][a-zA-Z]+){1,2}$/;
  return reg.test(email);
};
/**
 * 获取年，月，日
 */
exports.getYearMonthDay = date => {
  let [year, month, day] = [date.split('-')[0], date.split('-')[1], date.split('-')[2]];
  month = parseInt(month);
  day = parseInt(day);
  if (month < 10) {
    month = '0' + month;
  }
  if (day < 10) {
    day = '0' + day;
  }
  return { year, month, day };
};
/**
 * 判断是否需要验证token
 */
exports.isToken = (url, list) => {
  let state = false;
  list.forEach(item => {
    if (item.url === url) {
      state = item.isToken;
      return false;
    }
  });
  return state;
};
/**
 * 获取接口详情
 */
exports.getControllerInfo = (url, list) => {
  let controllerInfo = '';
  for (let i = 0, lens = list.length; i < lens; i++) {
    if (list[i].url === url) {
      controllerInfo = list[i];
      break;
    }
  }
  return controllerInfo;
};
/**
 * 解析base64
 */
exports.atob = a => {
  return new Buffer.from(a, 'base64').toString('binary');
};
/**
 * 转义特殊符号问题
 */
exports.escape = string => {
  if (typeof string !== 'string') {
    return string;
  }
  return string.split('').reduce((str, ch) => {
    switch (ch) {
      case '\n':
        str += '\\n';
        break;
      case "'":
        str += "\\'";
        break;
      case '"':
        str += '\\"';
        break;
      case '\t':
        str += '\\t';
        break;
      case '\0':
        str += '\\0';
        break;
      case '\r':
        str += '\\r';
        break;
      case '\b':
        str += '\\b';
        break;
      case '\x1a':
        str += '\\Z';
        break;
      case '\\':
        str += '\\\\';
        break;
      default:
        str += ch;
        break;
    }
    return str;
  }, '');
};
/**
 * 转义lIKE特殊符号问题
 */
exports.escapeLike = str => {
  return str.split('').reduce((str, ch) => {
    if (ch === '_' || ch === '%') {
      str += '\\';
    }
    str += ch;
    return str;
  }, '');
};
/**
 * 删除文件夹下的所有文件
 */
exports.delDir = path => {
  const fileDelDir = path => {
    let files = [];
    if (fs.existsSync(path)) {
      files = fs.readdirSync(path);
      files.forEach((file, index) => {
        let curPath = path + '/' + file;
        if (fs.statSync(curPath).isDirectory()) {
          fileDelDir(curPath); // 递归删除文件夹
        } else {
          fs.unlinkSync(curPath); // 删除文件
        }
      });
      fs.rmdirSync(path);
    }
  };
  fileDelDir(path);
};
/**
 * 获取本机IP地址
 */
exports.getIPAddress = () => {
  const interfaces = os.networkInterfaces();
  for (const devName in interfaces) {
    const iface = interfaces[devName];
    for (let i = 0; i < iface.length; i++) {
      const alias = iface[i];
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
        return alias.address;
      }
    }
  }
};
/**
 * 判断文件是否存在
 */
exports.isFileExisted = async path => {
  return new Promise((resolve, reject) => {
    fs.exists(path, exists => {
      resolve(exists);
    });
  });
};
/**
 * 获取本机ip
 */
exports.getLocalIp = () => {
  let interfaces = os.networkInterfaces();
  for (let devName in interfaces) {
    let iface = interfaces[devName];
    for (let i = 0; i < iface.length; i++) {
      let alias = iface[i];
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
        return alias.address;
      }
    }
  }
};
/**
 * 输出不同颜色
 * @param color 颜色键名
 * @returns {*}
 */
const colors = color => {
  const colorSet = {
    bright: '\x1B[1m', // 亮色
    grey: '\x1B[2m', // 灰色
    italic: '\x1B[3m', // 斜体
    underline: '\x1B[4m', // 下划线
    reverse: '\x1B[7m', // 反向
    hidden: '\x1B[8m', // 隐藏
    black: '\x1B[30m', // 黑色
    red: '\x1B[31m', // 红色
    green: '\x1B[32m', // 绿色
    yellow: '\x1B[33m', // 黄色
    blue: '\x1B[34m', // 蓝色
    magenta: '\x1B[35m', // 品红
    cyan: '\x1B[36m', // 青色
    white: '\x1B[37m', // 白色
    blackBG: '\x1B[40m', // 背景色为黑色
    redBG: '\x1B[41m', // 背景色为红色
    greenBG: '\x1B[42m', // 背景色为绿色
    yellowBG: '\x1B[43m', // 背景色为黄色
    blueBG: '\x1B[44m', // 背景色为蓝色
    magentaBG: '\x1B[45m', // 背景色为品红
    cyanBG: '\x1B[46m', // 背景色为青色
    whiteBG: '\x1B[47m' // 背景色为白色
  };
  return colorSet[color];
};
exports.logColor = colors;
/**
 * 去除字符串中的空格
 * @param string 字符
 */
exports.removeStrSpace = string => {
  return string.replace(/\s+/g, '');
};
/**
 * 转换对象的value为JSON_stringify
 */
exports.getObj_value_JSON_stringify = objects => {
  Object.keys(objects).forEach(key => {
    objects[key] = JSON.stringify(objects[key]);
  });
  return objects;
};
/**
 * 判断是否为文件
 */
exports.isFile = path => {
  return new Promise(resolve => {
    fs.access(path, fs.constants.F_OK, err => {
      resolve(!err);
    });
  }).then(state => state);
};
/**
 * 判断每个项目是否包含必须的index.html和index.js
 */
exports.isIndexHtmlJs = proPath => {
  const files = fs
    .readdirSync(proPath)
    .map(file => {
      // 当前项目路径
      const localPath = path.join(proPath, file);
      const folderSta = fs.statSync(localPath);
      if (!folderSta.isDirectory()) {
        return file;
      }
    })
    .filter(file => file);
  return files.includes('index.js') && files.includes('index.html');
};
/**
 * 是否包含config文件夹，以及是否判断是否包含system.dev.config、system.prod.config、systemConfig文件
 */
exports.isConfig = configPath => {
  if (fs.existsSync(configPath)) {
    const files = fs
      .readdirSync(configPath)
      .map(file => {
        // 当前项目路径
        const localPath = path.join(configPath, file);
        const folderSta = fs.statSync(localPath);
        if (!folderSta.isDirectory()) {
          return file;
        }
      })
      .filter(file => file);
    const state =
      files.includes('system.dev.config.js') &&
      files.includes('system.prod.config.js') &&
      files.includes('systemConfig.js');
    if (!state) {
      console.log(
        colors('yellow'),
        '警告：当前项目的配置文件没有按照约定，可以根据project目录下的README.md中目录规则来设置'
      );
    }
    return state;
  } else {
    console.log(colors('yellow'), '警告：当前项目没有配置文件');
    return false;
  }
};
/**
 * 判断文件是否存在
 */
exports.isFile = file => {
  return fs.existsSync(file);
};

/**
 * 复制文件
 * @param {*} srcDir 要拷贝的文件夹
 * @param {*} tarDir 目标文件夹
 * @param {*} cb 回调
 */
const copyFile = (srcPath, tarPath, cb) => {
  var rs = fs.createReadStream(srcPath);
  rs.on('error', function (err) {
    if (err) {
      console.log('read error', srcPath);
    }
    cb && cb(err);
  });

  var ws = fs.createWriteStream(tarPath);
  ws.on('error', function (err) {
    if (err) {
      console.log('write error', tarPath);
    }
    cb && cb(err);
  });

  ws.on('close', function (ex) {
    cb && cb(ex);
  });

  rs.pipe(ws);
};
exports.copyFile = copyFile;
/**
 * 拷贝文件夹内容到另一个文件夹内
 * @param {*} srcDir 要拷贝的文件夹
 * @param {*} tarDir 目标文件夹
 * @param {*} cb 回调
 */
const copySrcDirToTarDir = (srcDir, tarDir, cb) => {
  if (fs.existsSync(tarDir)) {
    fs.readdir(srcDir, (err, files) => {
      try {
        let count = 0;
        const checkEnd = () => {
          ++count == files.length && cb && cb();
        };
        if (err) {
          checkEnd();
          return;
        }
        files.forEach(file => {
          const srcPath = path.join(srcDir, file);
          const tarPath = path.join(tarDir, file);
          fs.stat(srcPath, function (err, stats) {
            if (stats.isDirectory()) {
              fs.mkdir(tarPath, function (err) {
                if (err) {
                  return;
                }
                copySrcDirToTarDir(srcPath, tarPath, checkEnd);
              });
            } else {
              copyFile(srcPath, tarPath, checkEnd);
            }
          });
        });
        // 为空时直接回调
        files.length === 0 && cb && cb();
      } catch (e) {
        console.log('异常了');
      }
    });
  } else {
    console.log(colors('yellow'), '警告：目标文件夹不存在！');
  }
};
exports.copySrcDirToTarDir = copySrcDirToTarDir;
